package com.coollang.smartbra.bleutil;

import android.content.Context;
import android.content.DialogInterface;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;

import com.coollang.smartbra.R;
import com.coollang.smartbra.base.MyApplication;
import com.coollang.smartbra.bleutil.callback.BleCallbackImpl;
import com.coollang.smartbra.fragment.FirstFragment;
import com.coollang.smartbra.utils.DataUtils;
import com.coollang.smartbra.utils.LogUtils;
import com.coollang.smartbra.utils.UIUtils;
import com.inuker.bluetooth.library.BluetoothClient;
import com.inuker.bluetooth.library.Code;
import com.inuker.bluetooth.library.Constants;
import com.inuker.bluetooth.library.connect.listener.BleConnectStatusListener;
import com.inuker.bluetooth.library.connect.listener.BluetoothStateListener;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.response.BleConnectResponse;
import com.inuker.bluetooth.library.connect.response.BleNotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleUnnotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleWriteResponse;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.search.SearchRequest;
import com.inuker.bluetooth.library.search.SearchResult;
import com.inuker.bluetooth.library.search.response.SearchResponse;
import com.inuker.bluetooth.library.utils.ByteUtils;
import com.inuker.bluetooth.library.utils.UUIDUtils;

import java.util.UUID;

import cn.pedant.sweetalert.SweetAlertDialog;

import static com.coollang.smartbra.utils.UIUtils.getString;
import static com.inuker.bluetooth.library.Constants.STATUS_CONNECTED;
import static com.inuker.bluetooth.library.Constants.STATUS_DISCONNECTED;

/**
 * 新版蓝牙工具类
 */

public class BleUtil {

    private static final String TAG = BleUtil.class.getSimpleName();
    private static volatile BleUtil instance = null;
    private static BluetoothClient mClient;

    // 连接的设备MAC地址
    private String connectDeviceMac = "";
    private SweetAlertDialog pDialog;

    private BleUtil() {

    }

    private static Context mContext;

    public static void init(Context context) {
        mContext = context;
        if (instance == null) {
            synchronized (BleUtil.class) {
                if (instance == null) {
                    mClient = new BluetoothClient(context);
                    instance = new BleUtil();
                }
            }
        }
    }

    public static BleUtil getInstance() {
        return instance;
    }

    // 是否支持ble蓝牙
    public boolean isBleSupported() {
        return mClient.isBleSupported();
    }

    // 判断蓝牙是否打开
    public boolean isBluetoothOpened() {
        return mClient.isBluetoothOpened();
    }

    // 打开蓝牙
    public void openBle() {
        if (!isBluetoothOpened()) {
            mClient.openBluetooth();
        }
    }

    // 关闭蓝牙
    public void closeBle() {
        if (isBluetoothOpened()) {
            mClient.closeBluetooth();
        }
    }

    /**
     * 注册蓝牙打开关闭时间的监听
     *
     * @param l
     */
    public void registerBluetoothStateListener(BluetoothStateListener l) {
        mClient.registerBluetoothStateListener(l);
    }

    /**
     * 取消蓝牙打开监听
     *
     * @param l
     */
    public void unregisterBluetoothStateListener(BluetoothStateListener l) {
        mClient.unregisterBluetoothStateListener(l);
    }

    /**
     * 扫描蓝牙
     */
    public void search() {
        SearchRequest request = new SearchRequest.Builder()
                .searchBluetoothLeDevice(3000, 3)   // 先扫BLE设备3次，每次3s
                .build();

        mClient.search(request, new SearchResponse() {
            @Override
            public void onSearchStarted() {

                if (mBleCallback != null) {
                    mBleCallback.onSearchStarted();
                }
            }

            @Override
            public void onDeviceFounded(SearchResult device) {
                if (mBleCallback != null) {
                    String name = device.getName();
                    if (!TextUtils.isEmpty(name) && name.contains("S002")) {
                        mBleCallback.onScan(device);
                    }
                }
            }

            @Override
            public void onSearchStopped() {
                if (mBleCallback != null) {
                    mBleCallback.onScanStop();
                }
            }

            @Override
            public void onSearchCanceled() {
                if (mBleCallback != null) {
                    mBleCallback.onScanStop();
                }
            }
        });
    }

    /**
     * 停止扫描
     */
    public void stopSearch() {
        mClient.stopSearch();
    }

    /**
     * 蓝牙连接
     */
    public void connect(String deviceMac) {
        this.connectDeviceMac = deviceMac;
        registerConnectStatusListener();
        BleConnectOptions options = new BleConnectOptions.Builder()
                .setConnectRetry(3)   // 连接如果失败重试3次
                .setConnectTimeout(30000)   // 连接超时30s
                .setServiceDiscoverRetry(3)  // 发现服务如果失败重试3次
                .setServiceDiscoverTimeout(20000)  // 发现服务超时20s
                .build();

        mClient.connect(deviceMac, options, new BleConnectResponse() {
            @Override
            public void onResponse(int code, BleGattProfile data) {

                if (mBleCallback == null) {
                    return;
                }
                if (code == Code.REQUEST_SUCCESS) {
                    mBleCallback.onBleConnected();
                } else if (code == Code.REQUEST_FAILED) {
                    mBleCallback.onBleDisconnected();
                }
            }
        });
    }

    /**
     * 断开连接
     */
    public void disconnect() {
        if (!TextUtils.isEmpty(connectDeviceMac)) {
            refreshCache();
            isDisConnect = true;
            mClient.disconnect(connectDeviceMac);
            connectDeviceMac = "";
        }
    }

    /**
     * 写入数据
     */
    public void write(byte[] bytes) {
        LogUtils.d("蓝牙发送消息", ByteUtils.byteToString(bytes));
        mClient.write(connectDeviceMac, getUUID(0001), getUUID(0002), bytes, new BleWriteResponse() {
            @Override
            public void onResponse(int code) {
                if (code == Code.REQUEST_SUCCESS) {
                } else if (code == Code.REQUEST_FAILED) {
                }
            }
        });
    }

    private BleCallbackImpl mBleCallback;

    public void registerNotifyListener(BleCallbackImpl callback) {
        this.mBleCallback = callback;
    }

    public void unRegisterNotifyListener() {
        mBleCallback = null;
    }

    /**
     * 开启通知
     */
    public void openNotify() {
        mClient.notify(connectDeviceMac, getUUID(0001), getUUID(0003), new BleNotifyResponse() {
            @Override
            public void onNotify(UUID service, UUID character, byte[] value) {
                LogUtils.d(TAG, "蓝牙通知消息: " + ByteUtils.byteToString(value));
                if (mBleCallback != null) {
                    mBleCallback.onNotify(value);
                }
            }

            @Override
            public void onResponse(int code) {
                if (code == Code.REQUEST_SUCCESS) {
                } else if (code == Code.REQUEST_FAILED) {

                }

            }
        });
    }

    /**
     * 关闭通知
     */
    public void closeNotify() {
        mClient.unnotify(connectDeviceMac, getUUID(0001), getUUID(0003), new BleUnnotifyResponse() {
            @Override
            public void onResponse(int code) {
                if (code == Code.REQUEST_SUCCESS) {

                }
            }
        });
    }

    /**
     * 蓝牙设备连接状态
     */
    public void registerConnectStatusListener() {
        mClient.registerConnectStatusListener(connectDeviceMac, mBleConnectStatusListener);
    }

    /**
     * 蓝牙设备主动断开
     */
    public void unregisterConnectStatusListener() {
        mClient.unregisterConnectStatusListener(connectDeviceMac, mBleConnectStatusListener);
    }

    private final BleConnectStatusListener mBleConnectStatusListener = new BleConnectStatusListener() {

        @Override
        public void onConnectStatusChanged(String mac, int status) {
            if (status == STATUS_CONNECTED) {
                // 连接成功
                openNotify();
                connectedSucceed();
            } else if (status == STATUS_DISCONNECTED) {
                disconnectDevice();
            }
        }
    };

    private void showUI() {
        boolean isActive = MyApplication.isActive;
        if (isActive) {
            showDisconnectedUI();
        }
    }

    public void refreshCache() {
        mClient.refreshCache(connectDeviceMac);
    }

    private UUID getUUID(int uuid) {
        return UUIDUtils.makeUUID(uuid);
    }

    /**
     * 获取已连接设备的Mac地址
     *
     * @return
     */
    public String getMac() {
        return connectDeviceMac;
    }

    /**
     * =================================== 发送数据 ===================================
     */
    public void sendData(byte... bs) {
        if (!TextUtils.isEmpty(connectDeviceMac)) {
            int connectStatus = mClient.getConnectStatus(connectDeviceMac);
            if (connectStatus == Constants.STATUS_DEVICE_CONNECTED) {
                // 如果设备在连接
                write(DataUtils.getDataToSend(bs));
            }
        }
    }

    /**
     * 判断设备是否连接中
     */
    public boolean isDecviceConnected() {
        int connectStatus = mClient.getConnectStatus(connectDeviceMac);
        return connectStatus == Constants.STATUS_DEVICE_CONNECTED;
    }

    /**
     * =================================== UI业务 ===================================
     */
    public void showDisconnectedUI() {
        if (pDialog != null && pDialog.isShowing()) {
            return;
        }

        pDialog = new SweetAlertDialog(UIUtils.getContext(), SweetAlertDialog.NORMAL_TYPE).setTitleText(getString(R.string.isConnectAgain));
        pDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        pDialog.setCancelable(false);
        pDialog.setConfirmText(getString(R.string.cancel));
        pDialog.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
            @Override
            public void onClick(SweetAlertDialog sweetAlertDialog) {
                sweetAlertDialog.dismiss();
            }
        });
        pDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    return true;
                }
                return false;
            }
        });
        pDialog.show();

        // 断线重连
        connect(getMac());
    }

    private void dismissDialog() {
        if (pDialog != null) {
            if (pDialog.isShowing()) {
                pDialog.dismiss();
                pDialog = null;
            }
        }
    }

    // =================================== 连接成功和断开连接业务逻辑 ===================================
    // 连接成功
    private void connectedSucceed() {

        isDisConnect = false;
        MyApplication.getApplication().isConnected = true;
        dismissDialog();

        if (!MyApplication.getApplication().isUpdating) {
            MyApplication.getApplication().getMainThreadHandler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    MyApplication.getApplication().sendDate();// 校准时间戳
                }
            }, 1000);
        }

        FirstFragment.imgvDeviceRight.setImageResource(R.drawable.device_connect);
        FirstFragment.imgvDeviceRight.clearAnimation();

        initBarrey();
        initVersion();
        initSteps();
    }

    // 断开连接
    private void disconnectDevice() {
        unregisterConnectStatusListener();
        // 断开
        if (mBleCallback != null) {
            mBleCallback.onBleDisconnected();
        }

        MyApplication.getApplication().isConnected = false;
        MyApplication.getApplication().betery = 0;

        FirstFragment.imgvDeviceRight.setImageResource(R.drawable.device_disconnect);
        FirstFragment.imgvDeviceRight.startAnimation(AnimationUtils.loadAnimation(UIUtils.getContext(), R.anim.anim_alpha));
        if (isDisConnect == false && mUINO) {
            showUI();
        }
    }

    private boolean isDisConnect;

    // ================================== 发送指令

    /**
     * 获取设备固件版本
     */
    private void initVersion() {
        sendData((byte) 0x21);
    }

    /**
     * 获取步数
     */
    private void initSteps() {
        sendData((byte) 0x38);
    }

    /**
     * 获取设备电量
     */
    private void initBarrey() {
        sendData((byte) 0x22);
    }

    /**
     * 是否弹出蓝牙断开连接ui
     */
    private boolean mUINO = true;

    public void setUINO(boolean UINO) {
        mUINO = UINO;
    }
}
